package main

import (
	"database/sql"
	"encoding/json"
	"io/ioutil"
	"net/http"
	"strconv"

	"test.com/fusion"
	"test.com/worlddb"
)

type ItemPrototype struct {
	ItemName string                 `json:"itemName"`
	ItemDesc string                 `json:"itemDesc"`
	ItemInfo *worlddb.ItemPrototype `json:"itemInfo"`
}

type itemWebPrototype struct {
	ItemPrototype
}

func handleGetItemDialogArgs(w http.ResponseWriter, r *http.Request) {
	scriptFiles, err := getAllScriptable(worldDB)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	lsRows, err := getAllLoot4DialogTable(worldDB)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	spellRows, err := getAllSpell4DialogTable(worldDB)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	dialogArgs := map[string]interface{}{
		"scriptFiles": scriptFiles,
		"lsRows":      lsRows,
		"spellRows":   spellRows,
	}
	jsonData, err := json.Marshal(dialogArgs)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJsonResponseData(w, jsonData)
}

func handleGetItemEnumType(w http.ResponseWriter, r *http.Request) {
	enumTypes := map[string]interface{}{
		"ScriptType": getEnumScriptType(),
	}
	jsonData, err := json.Marshal(enumTypes)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJsonResponseData(w, jsonData)
}

func handleGetItemUIView(w http.ResponseWriter, r *http.Request) {
	uiViews := map[string]interface{}{
		"ItemClassCascade": getViewItemClassCascade(),
		"ItemQuality":      getViewItemQuality(),
	}
	jsonData, err := json.Marshal(uiViews)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJsonResponseData(w, jsonData)
}

func handleGetItemTreeView(w http.ResponseWriter, r *http.Request) {
	handleGetEditorConstTreeView(w, r, worlddb.EditorTreeView_Type_Item,
		getViewItemClassCascade(), getAllItemNames, getAllItemClasses)
}

func handleSaveItemTreeView(w http.ResponseWriter, r *http.Request) {
	handleSaveEditorConstTreeView(w, r, worlddb.EditorTreeView_Type_Item)
}

func handleGetItemInstance(w http.ResponseWriter, r *http.Request) {
	itemTypeID, err := strconv.ParseUint(r.FormValue("ItemTypeID"), 0, 32)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	itemData, err := getItemInstanceJsonData(worldDB, uint32(itemTypeID))
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJsonResponseData(w, itemData)
}

func handleNewItemInstance(w http.ResponseWriter, r *http.Request) {
	itemName, itemDesc := r.FormValue("ItemName"), r.FormValue("ItemDesc")
	if itemName == "" {
		http.Error(w, "empty item name.", http.StatusBadRequest)
		return
	}
	var itemTypeID uint32
	err := fusion.RunDBTransaction(worldDB, func(tx *sql.Tx) (err error) {
		itemTypeID, err = newItemInstance(tx, itemName, itemDesc)
		return
	})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	itemData, err := getItemInstanceJsonData(worldDB, itemTypeID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJsonResponseData(w, itemData)
}

func handleCopyItemInstance(w http.ResponseWriter, r *http.Request) {
	itemTypeID, err := strconv.ParseUint(r.FormValue("ItemTypeID"), 0, 32)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	var ID uint32
	err = fusion.RunDBTransaction(worldDB, func(tx *sql.Tx) (err error) {
		ID, err = copyItemInstance(worldDB, tx, uint32(itemTypeID))
		return
	})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	itemData, err := getItemInstanceJsonData(worldDB, ID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJsonResponseData(w, itemData)
}

func handleDeleteItemInstance(w http.ResponseWriter, r *http.Request) {
	itemTypeID, err := strconv.ParseUint(r.FormValue("ItemTypeID"), 0, 32)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	err = fusion.RunDBTransaction(worldDB, func(tx *sql.Tx) error {
		return deleteItemInstance(tx, uint32(itemTypeID))
	})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeOKResponseData(w)
}

func handleSaveItemInstance(w http.ResponseWriter, r *http.Request) {
	itemData, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	var itemProto ItemPrototype
	if err = json.Unmarshal(itemData, &itemProto); err != nil {
		http.Error(w, err.Error(), http.StatusNotAcceptable)
		return
	}
	err = fusion.RunDBTransaction(worldDB, func(tx *sql.Tx) error {
		return saveItemInstance(tx, &itemProto)
	})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeOKResponseData(w)
}
